package com.smartboot.plus.service;

import com.smartboot.plus.condition.ConditionGroup;
import com.smartboot.plus.condition.ConditionQ;
import com.smartboot.plus.exception.ServiceException;
import com.smartboot.plus.ignite.IgniteCacheRegion;
import com.smartboot.plus.ignite.IgniteQueryExecutor;
import com.smartboot.plus.ignite.cache.MqttAuthCache;
import com.smartboot.plus.utils.Func;
import com.smartboot.plus.utils.SecurePasswordUtil;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.mindrot.BCrypt;
import tech.smartboot.feat.cloud.annotation.Autowired;
import tech.smartboot.feat.cloud.annotation.Bean;

import java.sql.Timestamp;
import java.util.Optional;

@Bean
public class MqttAuthService implements IgniteQueryExecutor<MqttAuthCache> {

    @Autowired
    private Ignite igniteInstance;


    @Override
    public IgniteCache<String, MqttAuthCache> getIgniteCache() {
        return igniteInstance.cache(IgniteCacheRegion.MQTT_AUTH_CACHE.getCacheName());
    }

    /**
     * 提交认证信息（新增或更新）
     * @param mqttAuthCache 认证对象
     * @return 是否提交成功
     */
    public boolean submit(MqttAuthCache mqttAuthCache) {
        // 表单合法性校验
        validateForm(mqttAuthCache);

        boolean isNew = Func.isEmpty(mqttAuthCache.getId());

        // 如果是新增，初始化ID
        if (isNew) {
            mqttAuthCache.setId(Func.randomUUID());
        }

        // 查询当前记录是否存在
        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAuthCache::getId, mqttAuthCache.getId()));
        MqttAuthCache existing = this.selectOne(conditionGroup, MqttAuthCache.class);

        if (existing == null) {
            // ---------- 新增 ----------
            String salt = BCrypt.gensalt(10);
            mqttAuthCache.setSalt(salt);

            String hashedPassword = SecurePasswordUtil.hashPassword(
                    mqttAuthCache.getPassword(),
                    salt,
                    mqttAuthCache.getEncryptionType(),
                    mqttAuthCache.getSaltType()
            );
            mqttAuthCache.setPassword(hashedPassword);

            Timestamp now = new Timestamp(System.currentTimeMillis());
            mqttAuthCache.setCreatedAt(now);
            mqttAuthCache.setUpdatedAt(now);

            getIgniteCache().put(mqttAuthCache.getUsername(), mqttAuthCache);
        } else {
            // ---------- 更新 ----------
            boolean needReHash = false;
//            if (!existing.getEncryptionType().equals(mqttAuthCache.getEncryptionType())) {
//                existing.setEncryptionType(mqttAuthCache.getEncryptionType());
//                needReHash = true;
//            }
//
//            if (!existing.getSaltType().equals(mqttAuthCache.getSaltType())) {
//                existing.setSaltType(mqttAuthCache.getSaltType());
//                needReHash = true;
//            }
            // 如果用户传入新密码，则标记需要重新加密
            if (Func.isNotEmpty(mqttAuthCache.getPassword())) {
                existing.setPassword(mqttAuthCache.getPassword());
                needReHash = true;
            }

            if (needReHash) {
                String hashedPassword = SecurePasswordUtil.hashPassword(
                        existing.getPassword(),
                        existing.getSalt(),
                        existing.getEncryptionType(),
                        existing.getSaltType()
                );
                existing.setPassword(hashedPassword);
            }

            existing.setStatus(mqttAuthCache.getStatus());
            existing.setRemark(mqttAuthCache.getRemark());
            existing.setUpdatedAt(new Timestamp(System.currentTimeMillis()));

            getIgniteCache().put(existing.getUsername(), existing);
        }

        return true;
    }

    /**
     * 删除用户认证信息
     * @param id 用户ID
     * @return 是否删除成功
     */
    public boolean removeId(String id) {
        if(Func.isEmpty(id)||Func.isBlank(id)){
            return false;
        }
        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAuthCache::getId, id));
        return this.remove(conditionGroup);
    }

    /**
     * 更新状态
     * @param id 用户ID
     * @param status 新状态值
     * @return 是否更新成功
     */
    public boolean updateStatus(String id, Integer status) {
        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAuthCache::getId, id));
        MqttAuthCache mqttAuthCache = this.selectOne(conditionGroup, MqttAuthCache.class);
        if (mqttAuthCache == null) {
            return false;
        }

        mqttAuthCache.setStatus(status);
        mqttAuthCache.setUpdatedAt(new Timestamp(System.currentTimeMillis()));
        getIgniteCache().put(mqttAuthCache.getUsername(), mqttAuthCache);

        return true;
    }

    /**
     * 表单验证逻辑（新增或更新前）
     * @param mqttAuthCache 表单数据
     */
    private void validateForm(MqttAuthCache mqttAuthCache) {
        // ---------- 基本字段校验 ----------
        if (Func.isBlank(mqttAuthCache.getUsername())) {
            throw new ServiceException("帐号不能为空!");
        }

        boolean isNew = Func.isEmpty(mqttAuthCache.getId());

        if (isNew && Func.isBlank(mqttAuthCache.getPassword())) {
            throw new ServiceException("密码不能为空!");
        }

        if (Func.isBlank(mqttAuthCache.getEncryptionType())) {
            throw new ServiceException("加密方式不能为空!");
        }

        // ---------- 长度限制 ----------
        if (mqttAuthCache.getUsername().length() > 20) {
            throw new ServiceException("帐号最大 20 个字符!");
        }

        if (Func.isNotEmpty(mqttAuthCache.getPassword()) && mqttAuthCache.getPassword().length() > 50) {
            throw new ServiceException("密码最大 50 个字符!");
        }

        String remark = Optional.ofNullable(mqttAuthCache.getRemark()).orElse("");
        if (remark.length() > 50) {
            throw new ServiceException("备注最大 50 个字符!");
        }

        // ---------- 唯一性校验（用户名不可重复） ----------
        ConditionGroup conditionGroup = new ConditionGroup()
                .add(new ConditionQ(MqttAuthCache::getUsername, mqttAuthCache.getUsername()));

        if (!isNew) {
            conditionGroup.add(new ConditionQ(MqttAuthCache::getId, ConditionQ.NOT_EQ, mqttAuthCache.getId()));
        }

        MqttAuthCache existed = this.selectOne(conditionGroup, MqttAuthCache.class);
        if (existed != null) {
            throw new ServiceException("当前帐号已存在!");
        }
    }

}
